package model;

import controller.VueloController;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import static model.Algoritmo.HORA_MILI;

// CLASE ENCARGADA DE REVISION DE LA LLEGADA Y PARTIDA DE VUELOS
class Revision {

    // metodo para revisar aquellos vuelos que llegaron a su destino a esta fecha y hora de la simulacion, actualizo capacidades de esos vuelos y de aeropuertos, asi como los paquetes
    public static void revisarLLegadaDeVuelos(Simulacion simulacion) {
        Date horaSimulacion = simulacion.getFechaHoraSim();
        List<Arista> listaArista = simulacion.getListaAristas();

        //Voy a recorrer todas las aristas
        for (int i = 0; i < listaArista.size(); i++) {
//            System.out.println("i: "+i);
            Vuelo vuelo = listaArista.get(i).getVuelo();
       
            
            Iterator<HistorialVuelo> iteradorHistorialVuelo = vuelo.getHistorialVuelos().iterator();
            while(iteradorHistorialVuelo.hasNext()){
                HistorialVuelo historialVueloTemp = iteradorHistorialVuelo.next();
                
                
                boolean llego = verificaDiferenciaLlegada(historialVueloTemp, horaSimulacion);
                
                if (llego){
//                    
//                    System.out.println("llego vuelo " + historialVueloTemp.getVuelo().getCiudadByIdCiudadOrigen().getCiudad() 
//                            + " - " + historialVueloTemp.getVuelo().getCiudadByIdCiudadDestino().getCiudad()
//                            + " " + historialVueloTemp.getId().getFecha());
                    Iterator<Paquete> paquetes = historialVueloTemp.getPaquetes().iterator();
                    while (paquetes.hasNext()){

                        Paquete paquete = paquetes.next();
                        Iterator<HistorialVuelo> historialVueloxPaquete = paquete.getHistorialVuelos().iterator();
                        HistorialVuelo ultimoVuelo = tomaUltimoVuelo(historialVueloxPaquete);



                            String ciudadActual = vuelo.getCiudadByIdCiudadDestino().getCiudad();
                            String ciudadFinal = ultimoVuelo.getVuelo().getCiudadByIdCiudadDestino().getCiudad();
                            //Si la ciudad actual no es la final, entonces es escala, por lo que hay que actualizar las capacidades
                            if (!ciudadFinal.equals(ciudadActual)) {
//                                System.out.println("escala");
                                //int actualCapacidadCiudad = vuelo.getCiudadByIdCiudadDestino().getCapDisp();
                                int actualCapacidadCiudad = listaArista.get(i).getNodoFinal().getCiudad().getCapDisp();
                                //Setear el estado a en espera al paquete
                                paquete.setEstado("Viajando hacia " + ciudadActual);
                                //Sumo uno de capacidad a la ciudad, ya que es escala.
                                //vuelo.getCiudadByIdCiudadDestino().setCapDisp(actualCapacidadCiudad - 1);
                                listaArista.get(i).getNodoFinal().getCiudad().setCapDisp(actualCapacidadCiudad - 1);
                                //System.out.println("paquete llego a " + vuelo.getCiudadByIdCiudadDestino().getCiudad() + " de " + vuelo.getCiudadByIdCiudadOrigen().getCiudad());
                            }
                            //la ciudad actual es la final
                            else{
                                // Setear el estado de entregado al paquete
                                paquete.setEstado("Entregado");
//                                System.out.println("entregado");
                            }

                    }
                }
            }
            
        }
    }

    // metodo para revisar aquellos vuelos que partieron de su origen a esta fecha y hora de la simulacion
    public static void revisarPartidaDeVuelos(Simulacion simulacion) {
        Date horaSimulacion = simulacion.getFechaHoraSim();
        List<Arista> listaArista = simulacion.getListaAristas();

        //Voy a recorrer todas las aristas
        for (int i = 0; i < listaArista.size(); i++) {
            Vuelo vuelo = listaArista.get(i).getVuelo();

            Iterator<HistorialVuelo> iteradorHistorialVuelo = vuelo.getHistorialVuelos().iterator();
            while(iteradorHistorialVuelo.hasNext()){
                HistorialVuelo historialVueloTemp = iteradorHistorialVuelo.next();
                
                boolean salio = verificaDiferencia(historialVueloTemp, horaSimulacion);
                
                if (salio) //Eso quiere decir que la hora de llegada es la del sistema
                {
                
//                    System.out.println("salio vuelo " + historialVueloTemp.getVuelo().getCiudadByIdCiudadOrigen().getCiudad() 
//                            + " - " + historialVueloTemp.getVuelo().getCiudadByIdCiudadDestino().getCiudad()
//                            + " " + historialVueloTemp.getId().getFecha());
                    Iterator<Paquete> iteradorPaquete = historialVueloTemp.getPaquetes().iterator();
                    while(iteradorPaquete.hasNext()){
                        Paquete paqueteTemp = iteradorPaquete.next();
                        //boolean salio = verificaDiferencia(paqueteTemp.getVuelo(), horaSimulacion);

                        //int actualCapacidadCiudad =  vuelo.getCiudadByIdCiudadOrigen().getCapDisp();
                        //int actualCapacidadCiudad  = vuelo.getCiudadByIdCiudadOrigen().getCapDisp();
                        int actualCapacidadCiudad  = listaArista.get(i).getNodoInicial().getCiudad().getCapDisp();
                        //Sumo uno a la capacidad del vuelo
                        //vuelo.setCapMax(actualCapacidadVuelo + 1);
                        //Setear el estado a enviado
                        paqueteTemp.setEstado("Viajando hacia " + listaArista.get(i).getNodoInicial().getCiudad().getCiudad());
                        //Resto uno de capacidad de la ciudad
                        //vuelo.getCiudadByIdCiudadOrigen().setCapDisp(actualCapacidadCiudad + 1);
                        listaArista.get(i).getNodoInicial().getCiudad().setCapDisp(actualCapacidadCiudad + 1);
                        //listaArista.get(i).getNodoInicial().getCiudad().setCapDisp(actualCapacidadCiudad + 1);
                        //System.out.println("paquete partio a " + vuelo.getCiudadByIdCiudadDestino().getCiudad() + " de " + vuelo.getCiudadByIdCiudadOrigen().getCiudad());
                    }
                }
            }
            
        }
    }

    
    private static boolean verificaDiferencia(HistorialVuelo historialVuelo, Date fechaHoraSimulacion) {

        Date horaPartida = historialVuelo.getId().getFecha();
        Calendar cal = Calendar.getInstance();
        cal.setTime(horaPartida);
        double diferenciaHoras = historialVuelo.getVuelo().getCiudadByIdCiudadOrigen().getDiferenciaHora();
        cal.add(Calendar.HOUR_OF_DAY,(int)diferenciaHoras) ;
        cal.add(Calendar.MINUTE, (int)((diferenciaHoras*60)%60));
        if (cal.getTime().getTime() == fechaHoraSimulacion.getTime())
            return true;
        else return false;
    }
    
    private static boolean verificaDiferenciaLlegada(HistorialVuelo historialVuelo, Date fechaHoraSimulacion) {

        Date horaPartida = historialVuelo.getId().getFecha();
        Calendar cal = Calendar.getInstance();
        cal.setTime(horaPartida);
        double diferenciaHoras = historialVuelo.getVuelo().getCiudadByIdCiudadOrigen().getDiferenciaHora();
        cal.add(Calendar.HOUR_OF_DAY,(int)diferenciaHoras) ;
        cal.add(Calendar.MINUTE, (int)((diferenciaHoras*60)%60));
        double horasViaje = Algoritmo.diferenciaHoras(historialVuelo.getVuelo().getHoraPartida().getTime() + (long)(historialVuelo.getVuelo().getCiudadByIdCiudadOrigen().getDiferenciaHora()*HORA_MILI),
                    historialVuelo.getVuelo().getHoraLlegada().getTime() + (long)(historialVuelo.getVuelo().getCiudadByIdCiudadDestino().getDiferenciaHora()*HORA_MILI));
        //System.out.println("minutosViaje: " + minutosViaje);
        cal.add(Calendar.HOUR_OF_DAY,(int)(horasViaje));
        cal.add(Calendar.MINUTE, (int)((horasViaje*60)%60));
        if (cal.getTime().getTime() == fechaHoraSimulacion.getTime())
            return true;
        else return false;
    }

//    private static Vuelo tomaUltimoVuelo(Iterator<HistorialVuelo> historialVueloxPaquete) {
//        Date fecha = new Date(0);
//        Vuelo ultimoVuelo = null;
//
//        while (historialVueloxPaquete.hasNext()) {
//            HistorialVuelo historialVuelo = historialVueloxPaquete.next();
//            Date fechaVuelo = historialVuelo.getId().getFecha();
//
//            if (fecha.compareTo(fechaVuelo) < 0) {
//                //Veo cuál fecha es mayor/menor y reasigno
//                fecha = fechaVuelo;
//                ultimoVuelo = historialVuelo.getVuelo();
//            }
//        }
//        return ultimoVuelo;
//    }
    
    private static HistorialVuelo tomaUltimoVuelo(Iterator<HistorialVuelo> historialVueloxPaquete) {
        Date fecha = new Date(0);
        HistorialVuelo ultimoVuelo = null;

        while (historialVueloxPaquete.hasNext()) {
            HistorialVuelo historialVuelo = historialVueloxPaquete.next();
            Date fechaVuelo = historialVuelo.getId().getFecha();

            if (fecha.compareTo(fechaVuelo) < 0) {
                //Veo cuál fecha es mayor/menor y reasigno
                fecha = fechaVuelo;
                ultimoVuelo = historialVuelo;
            }
        }
        return ultimoVuelo;
    }
    
    
    public static void revisarLLegadaDeVuelos(SimulacionTracking simulacion) {
        Date horaSimulacion = simulacion.getFechaActualSim();
        List<Arista> listaArista = simulacion.getListaAristas();

        //Voy a recorrer todas las aristas
        for (int i = 0; i < listaArista.size(); i++) {
            Vuelo vuelo = listaArista.get(i).getVuelo();
       
            
            Iterator<HistorialVuelo> iteradorHistorialVuelo = vuelo.getHistorialVuelos().iterator();
            while(iteradorHistorialVuelo.hasNext()){
                HistorialVuelo historialVueloTemp = iteradorHistorialVuelo.next();
                
                
                boolean llego = verificaDiferenciaLlegada(historialVueloTemp, horaSimulacion);
                
                if (llego){
//                    
//                    System.out.println("llego vuelo " + historialVueloTemp.getVuelo().getCiudadByIdCiudadOrigen().getCiudad() 
//                            + " - " + historialVueloTemp.getVuelo().getCiudadByIdCiudadDestino().getCiudad()
//                            + " " + historialVueloTemp.getId().getFecha());
                    Iterator<Paquete> paquetes = historialVueloTemp.getPaquetes().iterator();
                    while (paquetes.hasNext()){

                        Paquete paquete = paquetes.next();
                        Iterator<HistorialVuelo> historialVueloxPaquete = paquete.getHistorialVuelos().iterator();
                        HistorialVuelo ultimoVuelo = tomaUltimoVuelo(historialVueloxPaquete);



                            String ciudadActual = vuelo.getCiudadByIdCiudadDestino().getCiudad();
                            //String ciudadFinal = ultimoVuelo.getVuelo().getCiudadByIdCiudadDestino().getCiudad();
                            Vuelo vueloFinal = VueloController.buscarVueloXId_ListaAristas(ultimoVuelo.getId().getIdVuelo(),simulacion.getListaAristas());
                            String ciudadFinal = vueloFinal.getCiudadByIdCiudadDestino().getCiudad();
                            //Si la ciudad actual no es la final, entonces es escala, por lo que hay que actualizar las capacidades
                            if (!ciudadFinal.equals(ciudadActual)) {
                                //System.out.println("escala");
                                //int actualCapacidadCiudad = vuelo.getCiudadByIdCiudadDestino().getCapDisp();
                                int actualCapacidadCiudad = listaArista.get(i).getNodoFinal().getCiudad().getCapDisp();
                                //Setear el estado a en espera al paquete
                                paquete.setEstado("Viajando hacia " + ciudadActual);
                                //Sumo uno de capacidad a la ciudad, ya que es escala.
                                //vuelo.getCiudadByIdCiudadDestino().setCapDisp(actualCapacidadCiudad - 1);
                                listaArista.get(i).getNodoFinal().getCiudad().setCapDisp(actualCapacidadCiudad - 1);
                                //System.out.println("paquete llego a " + vuelo.getCiudadByIdCiudadDestino().getCiudad() + " de " + vuelo.getCiudadByIdCiudadOrigen().getCiudad());
                            }
                            //la ciudad actual es la final
                            else{
                                // Setear el estado de entregado al paquete
                                paquete.setEstado("Entregado");
                            }

                    }
                }
            }
            
        }
    }
    
    
    public static void revisarPartidaDeVuelos(SimulacionTracking simulacion) {
        Date horaSimulacion = simulacion.getFechaActualSim();
        List<Arista> listaArista = simulacion.getListaAristas();

        //Voy a recorrer todas las aristas
        for (int i = 0; i < listaArista.size(); i++) {
            Vuelo vuelo = listaArista.get(i).getVuelo();

            Iterator<HistorialVuelo> iteradorHistorialVuelo = vuelo.getHistorialVuelos().iterator();
            while(iteradorHistorialVuelo.hasNext()){
                HistorialVuelo historialVueloTemp = iteradorHistorialVuelo.next();
                
                boolean salio = verificaDiferencia(historialVueloTemp, horaSimulacion);
                
                if (salio) //Eso quiere decir que la hora de llegada es la del sistema
                {
                
//                    System.out.println("salio vuelo " + historialVueloTemp.getVuelo().getCiudadByIdCiudadOrigen().getCiudad() 
//                            + " - " + historialVueloTemp.getVuelo().getCiudadByIdCiudadDestino().getCiudad()
//                            + " " + historialVueloTemp.getId().getFecha());
                    Iterator<Paquete> iteradorPaquete = historialVueloTemp.getPaquetes().iterator();
                    while(iteradorPaquete.hasNext()){
                        Paquete paqueteTemp = iteradorPaquete.next();
                        //boolean salio = verificaDiferencia(paqueteTemp.getVuelo(), horaSimulacion);

                        //int actualCapacidadCiudad =  vuelo.getCiudadByIdCiudadOrigen().getCapDisp();
                        //int actualCapacidadCiudad  = vuelo.getCiudadByIdCiudadOrigen().getCapDisp();
                        int actualCapacidadCiudad  = listaArista.get(i).getNodoInicial().getCiudad().getCapDisp();
                        //Sumo uno a la capacidad del vuelo
                        //vuelo.setCapMax(actualCapacidadVuelo + 1);
                        //Setear el estado a enviado
                        paqueteTemp.setEstado("Viajando hacia " + listaArista.get(i).getNodoFinal().getCiudad().getCiudad());
                        //Resto uno de capacidad de la ciudad
                        //vuelo.getCiudadByIdCiudadOrigen().setCapDisp(actualCapacidadCiudad + 1);
                        listaArista.get(i).getNodoInicial().getCiudad().setCapDisp(actualCapacidadCiudad + 1);
                        //listaArista.get(i).getNodoInicial().getCiudad().setCapDisp(actualCapacidadCiudad + 1);
                        //System.out.println("paquete partio a " + vuelo.getCiudadByIdCiudadDestino().getCiudad() + " de " + vuelo.getCiudadByIdCiudadOrigen().getCiudad());
                    }
                }
            }
            
        }
    }
    
}
